package cim2;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.IOUtils;

import com.googlecode.fannj.Fann;

public class RunNet {
	
	private Config cfg;
	
	public RunNet(Config cfg){
		this.cfg = cfg;
	}
	
	public void test() {		
		try {
	        File temp = File.createTempFile("fannj_", ".tmp");
	        temp.deleteOnExit();
	        
	        String testFile = cfg.getDataFile() + ".test";
	        System.out.println("Cargando el archivo de datos de prueba: " + testFile);
	        System.out.println();
	        
	        BufferedReader br = new BufferedReader(new FileReader("./data/" + testFile));	        
	        String line;
	        
	        List<List<Float>> testDataList = new ArrayList<List<Float>>();
	        List<List<Float>> expectedResults = new ArrayList<List<Float>>();
	        
	        boolean testDataLine = true;
	        
	        while ((line = br.readLine()) != null) {
	        	if (line.trim().length() > 0){
		        	String[] tokens = line.split(" ");
	
	        		List<Float> data = new ArrayList<Float>();
	        		for (int i = 0; i < tokens.length; i++){
	        			data.add(Float.valueOf(tokens[i]));
	        		}
	        		if (testDataLine){
	        			testDataList.add(data);
	        			testDataLine = false;
	        		} else {
	        			expectedResults.add(data);
	        			testDataLine = true;
	        		}
	        	} else {
	        		break;
	        	}
	        }
	        br.close();
	        
	        if (cfg.isShowTestData()){	        
		        System.out.println("Test Data: ");
		        for (int i = 0; i < testDataList.size(); i++){	        	
		        	System.out.println(testDataList.get(i) + " | " + expectedResults.get(i));
		        }	        	        	
	        }
	        	        	        
	        for (RedParam r : cfg.getRedes()){	        	
		        int success = 0;
		        int fail = 0;	        	
	        	String netFile = cfg.getDataFile() + "." + r.getNombre() + ".net";
	        	System.out.println("Red: " + r.getNombre() + " -- Cargando archivo de red " + netFile);
		        IOUtils.copy(new FileInputStream("./results/" + netFile), new FileOutputStream(temp));	        
	
		        Fann fann = new Fann(temp.getPath());
		        		        
		        for (int j = 0; j < testDataList.size(); j++){
		        	List<Float> td = testDataList.get(j);
		        	float[] testData = new float[td.size()];
		        	for (int i = 0; i < testData.length; i++){
		        		testData[i] = td.get(i);
		        	}		        	
			        
			        float[] result = fann.run(testData);
			        float got = result[0];
			        List<Float> expected = expectedResults.get(j);
			        List<Float> res = new ArrayList<Float>();
			        
			        for (float f : result){
			        	res.add(f);
			        }
			        			        
			        if (compareResults(expected, res, expectedResults.size())){
			        	if (cfg.isShowTestDetail()){
			        		System.out.println("OK    - Expected: " + expected + " got " + got);
			        	}
			        	success++;
			        } else {
			        	if (cfg.isShowTestDetail()){
			        		System.out.println("ERROR - Expected: " + expected + " got " + got);
			        	}
			        	fail++;
			        }			        
		        }
		        float rate = (new Float(success) / new Float(testDataList.size())) * 100;
		        int tot = success + fail;
		        System.out.println("OK: " + success + "/" + tot + " ER: " + fail + "/" + tot + " --- Tasa: " + rate + "%");
		        System.out.println();
	        }
	        
		} catch (Exception e){
			e.printStackTrace();
		}		
	}
	
	private boolean compareResults(List<Float> expected, List<Float> got, Integer possibleValues){
		for (int i = 0; i < expected.size(); i++){
			float e = expected.get(i);
			float g = got.get(i);
			boolean enRango = g >= e - 0.5 && g < e + 0.5; 
			if (!enRango){
				return false;
			}
		}
		return true;
	}	
}
